package com.su.sweet.aop;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import com.su.sweet.annotation.Wrapper;
import com.su.sweet.config.BaseWrapper;
import com.su.sweet.exception.ServiceException;
import org.noear.solon.annotation.Component;
import org.noear.solon.core.handle.Action;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.Handler;
import org.noear.solon.core.handle.Result;
import org.noear.solon.core.route.RouterInterceptor;
import org.noear.solon.core.route.RouterInterceptorChain;

import java.util.*;

@Component
public class WrapperAop implements RouterInterceptor {

    @Override
    public void doIntercept(Context ctx, Handler mainHandler, RouterInterceptorChain chain) throws Throwable {
        chain.doIntercept(ctx, mainHandler);
    }

    @Override
    public Object postResult(Context ctx, Object result) {
        Action action = ctx.action();
        Wrapper wrapper = null;
        if (action != null) {
            wrapper = action.method().getAnnotation(Wrapper.class);
        }
        if (wrapper == null) {
            return result;
        } else {
            if(result.toString().contains("Exception")){
                throw new ServiceException(result.toString());
            }
            Result res = (Result) result;
            Object beWrapped = res.getData();
            Class<? extends BaseWrapper<?>>[] baseWrapperClasses = wrapper.value();

            if (res.getData() == null || res.getCode() != 200) {
                return result;
            } else if (beWrapped instanceof Collection) {
                Collection collection = (Collection) beWrapped;
                ArrayList<Map<String, Object>> maps = new ArrayList();

                for (Object wrappedItem : collection) {
                    maps.add(this.wrapPureObject(wrappedItem, baseWrapperClasses));
                }
                res.setData(maps);
            } else if (ArrayUtil.isArray(beWrapped)) {
                List objects = (List) beWrapped;
                ArrayList<Map<String, Object>> maps = new ArrayList();

                for (Object wrappedItem : objects) {
                    maps.add(this.wrapPureObject(wrappedItem, baseWrapperClasses));
                }

                res.setData(maps);
            } else if (beWrapped instanceof Map) {
                Map map = (Map) beWrapped;
                if (map.get("list") != null && map.get("total") != null) {
                    List objects = (List) map.get("list");
                    ArrayList<Map<String, Object>> maps = new ArrayList();

                    for (Object wrappedItem : objects) {
                        maps.add(this.wrapPureObject(wrappedItem, baseWrapperClasses));
                    }

                    map.put("list", maps);
                    res.setData(map);
                }else {
                    res.setData(this.wrapPureObject(beWrapped, baseWrapperClasses));
                }
            } else {
                if (ObjectUtil.isEmpty(baseWrapperClasses)) {
                    return result;
                } else if (!(result instanceof Result)) {
                    System.out.println("当前请求的返回结果不是ResponseData类型，直接返回原值！");
                    return result;
                } else {
                    res.setData(this.wrapPureObject(beWrapped, baseWrapperClasses));
                }
            }
            return res;
        }
    }

    private Map<String, Object> wrapPureObject(Object originModel, Class<? extends BaseWrapper<?>>[] baseWrapperClasses) {
        if (originModel == null) {
            return new HashMap<>();
        }

        //Map<String, Object> originMap = BeanUtil.beanToMap(originModel);

        try {
            for (Class<? extends BaseWrapper<?>> baseWrapperClass : baseWrapperClasses) {
                BaseWrapper baseWrapper = baseWrapperClass.newInstance();
                Map<String, Object> incrementFieldsMap = baseWrapper.doWrap(originModel);
                return incrementFieldsMap;
            }
        } catch (Exception e) {
            System.out.println("原始对象包装过程，字段转化异常：{}" + e.getMessage());
            e.printStackTrace();
        }
        return null;
    }
}
